﻿using UnityEngine;

public class ParticleTimeGetter : MonoBehaviour
{
    
    // 除循环发射器以外粒子系统最大播放时间
    public float playTime;
    // 是否含有循环的粒子发射器
    public bool loop;

    public float GetPlayTime(bool useCache = true)
    {
        if (this.playTime != -1 && useCache)
            return this.playTime;
        
        this.playTime = GetTime(ref loop);
        return this.playTime;
    }

    private float GetTime(ref bool isLoop)
    {
        isLoop = false;
        var ret = 0f;
        var particles = this.transform.GetComponentsInChildren<ParticleSystem>();
        if (particles != null && particles.Length > 0)
        {
            foreach (var ps in particles)
            {
                var t = GetParticlePlayTime(ps);
                if (t > ret)
                    ret = t;
                
                if (ps.main.loop) {
                    isLoop = true;
                }
            }   
        }
        else
        {
            ret = 5;
        }

        return ret;
    }

    private float GetParticlePlayTime(ParticleSystem p)
    {
        if (!p.emission.enabled) return 0f;

        var main = p.main;
        if (main.loop)
            return -1f;
        
        /*if (GetMaxValue(p.emission.rateOverTime) <= 0)
            return GetMaxValue(p.main.startDelay) + GetMaxValue(main.startLifetime);*/

        return GetMaxValue(main.startDelay) +
               Mathf.Max(main.duration, GetMaxValue(main.startLifetime));
    }
    
    private float GetMaxValue(ParticleSystem.MinMaxCurve minMaxCurve)
    {
        switch (minMaxCurve.mode)
        {
            case ParticleSystemCurveMode.Constant:
                return minMaxCurve.constant;
            case ParticleSystemCurveMode.Curve:
                return GetCurveEnd(minMaxCurve.curve);
            case ParticleSystemCurveMode.TwoConstants:
                return Mathf.Max(minMaxCurve.constantMax,minMaxCurve.constantMin);
            case ParticleSystemCurveMode.TwoCurves:
                var ret1 = GetCurveEnd(minMaxCurve.curveMin);
                var ret2 = GetCurveEnd(minMaxCurve.curveMax);
                return ret1 > ret2 ? ret1 : ret2;
        }
        
        return -1f;
    }

    private float GetCurveEnd(AnimationCurve curve)
    {
        var ret = 0f;
        foreach (var key in curve.keys)
        {
            if (key.time > ret)
                ret = key.time;
        }

        return ret;
    }
}
